package com.robot;

import com.game.majiang.algorithm.PaperCard;
import com.game.majiang.algorithm.chexuan.ChexuanCardType;
import com.game.majiang.algorithm.chexuan.GameAlgorithm;
import com.game.majiang.config.ChexuanStructrue;
import com.game.majiang.config.LogManager;
import com.game.majiang.logic.LogicClient;
import com.game.majiang.logic.LogicPlayer;
import com.game.majiang.logic.LogicServer;
import com.game.majiang.logic.LogicTable;
import com.game.majiang.logic.chexuan.ChexuanPlayer;
import com.game.majiang.logic.chexuan.ChexuanTabale;
import com.game.majiang.logic.chexuan.ChexuanTableStatus;
import com.game.server.system.AbstractPlayer;
import com.game.server.util.Util;

import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Getter
@Setter
public class RobotClient {

	private LogicClient client;

	private int operateTime = 0;

	private boolean operateBool = false;

	private int grateCardsProbability = 0; // 0 - 100；100 为必定好牌； 0 为必定随机发牌；

	public void timeEvent() {
		if(this.client.getTable() == null) {
			return;
		}
		LogicTable table = (LogicTable) client.getTable();
		LogManager.getInstance().Log("now operator on table is " + table.getOperateUid());
		LogManager.getInstance().Log("the table status is " + table.getChexuanStatus());
		Consumer<Consumer<LogicTable>> robotOptF = (Consumer<LogicTable> operator) -> {
			boolean isTime2Opt = operateTime <= 0; // 如果操作时间小于等于零
			if(operateBool && isTime2Opt) {
				operateBool = false;
				operator.accept(table);
			} else if(operateBool) {
				operateTime -= 1;
			} else {
				operateBool = true;
				operateTime = Util.random(4) + 2;
			}
		};
		if(table.getChexuanStatus() == ChexuanTableStatus.WAIT || table.getChexuanStatus() == ChexuanTableStatus.READ) {
			this.operateBool = false;
			takeASeat(table);
		} else if(table.getChexuanStatus() == ChexuanTableStatus.BET && table.getOperateUid() == this.client.getUserId() && table.getOperateTime() > 5) {
			robotOptF.accept(this::bet); // 下注
		} else if(table.getChexuanStatus() == ChexuanTableStatus.GROUPCARDS ) {
			robotOptF.accept(this::categoryCards); // 组牌
		}
	}

	public void create(LogicTable table, Integer id) {
		LogManager.getInstance().Log("创建动态机器人：" + table);
		table.setRobotMaxId(table.getRobotMaxId() + 1);
		this.client = new LogicClient(id); // 从数据库读取机器人信息
		LogicServer.getInstance().addClient(this.client);
	}

	private void bet(LogicTable table) {
		ChexuanTabale ct = (ChexuanTabale) table;
		ChexuanStructrue struct = (ChexuanStructrue) ct.getCreate();
		LogManager.getInstance().Log("机器人 " + this.client.getUserId() + " 开始下注！");
		if(!ct.isCurrRoundBetBool()) {
			ct.gameOperate(this.client, 1, 0);
		} else {
			ChexuanPlayer player = (ChexuanPlayer) ct.getPlayer(this.client.getUserId());
			if((player.getBetBobo() + player.getUsebobo()) > ct.getMaxBet()) {
				ct.gameOperate(this.client, 5, 0);
			} else {
				List<PaperCard> handCards = player.getListHand();
				if(handCards.size() >= 2) {
					// 有大牌则敲
					boolean canQiao = ownGrateCardGroup(handCards, struct.getDijiuwang() == 1); // 有大牌
					if(canQiao) {
						ct.gameOperate(this.client, 2, 0);
						return;
					}
				}
				// ct.gameOperate(this.client, 2, 0);
				// 无大牌则休/丢
				int prop = Util.random(100);
				if (prop > 20) {
					ct.gameOperate(this.client, 0, 0);
				} else {
					ct.gameOperate(this.client, 1, 0);
				}
			}
		}
	}
	
	private void takeASeat(LogicTable table) {
		ChexuanTabale ct = (ChexuanTabale) table;
		int currentIntegral = this.client.getVo().getIntegral();
		if (currentIntegral < ct.getGameStartMinScore()) {
			LogManager.getInstance().Log("机器人余额不足, 机器人当前余额：" + currentIntegral + "; 房间要求最少： " + ct.getGameStartMinScore());
			return;
		}
		ChexuanPlayer player = (ChexuanPlayer) table.getPlayer(this.client.getUserId());
		if(player == null) {
			LogManager.getInstance().Log("机器人 " + this.client.getUserId() + "上桌");
			int seatNo = -1;
			for (int i = 0; i < table.getCreate().getGamesPeopleCount(); i++) {
				boolean haveBool = false;
				for (AbstractPlayer abPlayer : table.getPlayers()) {
					LogicPlayer tempPlayer = (LogicPlayer) abPlayer;
					if(tempPlayer.getSeatNo() == i) {
						haveBool = true;
						break;
					}
				}
				if(!haveBool) {
					seatNo = i;
					break; 
				}
			}
			if(seatNo != -1) {
				table.sitDown(this.client, seatNo);
			}
		} else {
			LogManager.getInstance().Log("机器人 " + this.client.getUserId() + " 已上桌, 开始设置bobo");
			setUpBobo(table);
		}
	}

	private void setUpBobo(LogicTable table) {
		ChexuanTabale ct = (ChexuanTabale) table;
		ChexuanPlayer player = (ChexuanPlayer) ct.getPlayer(this.client.getUserId());
		if(player != null) {
			if(player.getUsebobo() < ct.getGameStartMinScore()) {
				ct.setUpBobo(this.client, ct.getCreate().getDifen() * 50);
			}
		}
	}

	private void categoryCards(LogicTable table) {
		LogManager.getInstance().Log("机器人 " + this.client.getUserId() + " 开始组牌");
		ChexuanTabale ct = (ChexuanTabale) table;
		Object playerObj = ct.getPlayer(this.client.getUserId());
		if(!(playerObj instanceof ChexuanPlayer)) return;
		ChexuanPlayer player = (ChexuanPlayer) playerObj;
		ChexuanStructrue struct = (ChexuanStructrue) ct.getCreate();
		List<PaperCard> handCards = player.getListHand();
		LogManager.getInstance().Log("机器人 " + this.client.getUserId() + " 的手牌为：" + handCards);

		if(player.getListHand().size() != 4) return; // 手牌小于4张 不操作
		int maximumScore = 0;
		List<Integer> finalHandCardFront = new ArrayList<>();
		List<Integer> finalHandCardAfter = new ArrayList<>();
		for(int i = 0; i < 4; i += 1) {
			List<PaperCard> templateFrontCards = new ArrayList<>();
			List<PaperCard> templateAfterCards = new ArrayList<>(handCards);
			templateAfterCards.remove(handCards.get(i));
			templateFrontCards.add(handCards.get(i));
			for(int j = i + 1; j < 4; j += 1) {
				templateFrontCards.add(handCards.get(j));
				templateAfterCards.remove(handCards.get(j));
				ChexuanCardType chexuanFrontCardType = GameAlgorithm.checkCardType(templateFrontCards, struct.getDijiuwang() == 1);
				ChexuanCardType chexuanAfterCardType = GameAlgorithm.checkCardType(templateAfterCards, struct.getDijiuwang() == 1);
				int chexuanCardTypeValue = chexuanFrontCardType.getValue() + chexuanAfterCardType.getValue();
				if(maximumScore < chexuanCardTypeValue) {
					maximumScore = chexuanCardTypeValue;
					finalHandCardFront.clear();
					finalHandCardAfter.clear();
					finalHandCardFront.addAll(templateFrontCards.stream().map(PaperCard::getId).collect(Collectors.toList()));
					finalHandCardAfter.addAll(templateAfterCards.stream().map(PaperCard::getId).collect(Collectors.toList()));
				}
				templateAfterCards.add(handCards.get(j));
				templateFrontCards.remove(handCards.get(j));
			}
		}
		ct.operateGroupCards(client, finalHandCardFront, finalHandCardAfter);
	}

	private boolean ownGrateCardGroup(List<PaperCard> cards, boolean isDijiuwang) {
		int cardsCnt = cards.size();
		for(int i = 0; i < cardsCnt; i += 1) {
			for(int j = i + 1; j < cardsCnt; j += 1) {
				ChexuanCardType chexuanCardType = GameAlgorithm.checkCardType(Arrays.asList(cards.get(i), cards.get(j)),
						isDijiuwang);
				if(chexuanCardType.getValue() > 171) { // 非杂牌
					return true;
				}
			}
		}
		return false;
	}

}
